package com.ssy.lingxi.platform.manage.serviceimpl.content;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.platform.manage.constant.ColumnTypeEnum;
import com.ssy.lingxi.platform.manage.constant.CommonBooleanEnum;
import com.ssy.lingxi.platform.manage.constant.RecommendLabelEnum;
import com.ssy.lingxi.platform.manage.constant.ShelfEnum;
import com.ssy.lingxi.platform.manage.entity.content.*;
import com.ssy.lingxi.platform.manage.model.request.common.*;
import com.ssy.lingxi.platform.manage.model.request.content.*;
import com.ssy.lingxi.platform.manage.model.response.*;
import com.ssy.lingxi.platform.manage.repository.*;
import com.ssy.lingxi.platform.manage.service.content.IContentInformationService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 资讯管理 - 业务实现层
 *
 * @author fhj
 * @version 2.0.0
 * @date 2020/9/18
 */
@Slf4j
@Service
public class ContentInformationServiceImpl implements IContentInformationService {

    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Resource
    private ContentInformationRepository contentInformationRepository;
    @Resource
    private ContentColumnRepository contentColumnRepository;
    @Resource
    private ContentLabelRepository contentLabelRepository;
    @Resource
    private ContentInformationCollectRepository contentInformationCollectRepository;
    @Resource
    private ContentCategoryRepository contentCategoryRepository;

    @Override
    @ApiOperation(value = "列表")
    public Wrapper<PageData<ContentInformationPageResponse>> page(ContentInformationPageRequest request) {
        StringBuilder sbList = new StringBuilder(" SELECT * FROM man_content_information ci WHERE 1 = 1 ");
        StringBuilder sbCount = new StringBuilder(" SELECT count(ci.id) FROM man_content_information ci WHERE 1 = 1 ");

        String where = "";
        if (StringUtils.isNotBlank(request.getTitle())) {
            where += " AND ci.title LIKE '%" + request.getTitle() + "%' ";
        }
        if (request.getType() != null) {
            List<ContentColumn> columnList = contentColumnRepository.findAllByStatusAndType(CommonBooleanEnum.YES.getCode(), request.getType());
            if (CollectionUtil.isNotEmpty(columnList)) {
                List<Long> columnIdList = columnList.stream().map(ContentColumn::getId).collect(Collectors.toList());
                where += " AND ci.column_id IN(" + StringUtils.join(columnIdList, ",") + ")";
            }
        }
        if (request.getColumnId() != null) {
            where += " AND ci.column_id = " + request.getColumnId();
        }
        if (request.getThirdlyCategoryId() != null) {
            where += " AND ci.thirdly_category_id = " + request.getThirdlyCategoryId();
        }
        if (request.getRecommendLabel() != null) {
            where += " AND ci.recommend_label = " + request.getRecommendLabel();
        }
        if (request.getStatus() != null) {
            where += " AND ci.status = " + request.getStatus();
        }
        if (request.getLabelId() != null) {
            where += " AND ci.label_ids @> '" + request.getLabelId() + "'::jsonb ";
        }
        if (request.getStartTime() != null) {
            where += " AND ci.create_time >= " + request.getStartTime();
        }
        if (request.getEndTime() != null) {
            where += " AND ci.create_time <= " + request.getEndTime();
        }
        sbList.append(where);
        sbCount.append(where);

        sbList.append(" ORDER BY ci.create_time DESC ");
        sbList.append(" LIMIT ").append(request.getPageSize());
        sbList.append(" OFFSET ").append((request.getCurrent() - 1) * request.getPageSize());

        List<ContentInformationPageResponse> list = jdbcTemplate.query(sbList.toString(), new BeanPropertyRowMapper<>(ContentInformationPageResponse.class));
        Long totalCount = jdbcTemplate.queryForObject(sbCount.toString(), Long.class);

        //获取所有栏目、分类
        List<ContentColumn> allColumn = contentColumnRepository.findAll();
        List<ContentCategory> allCategory = contentCategoryRepository.findAll();

        //封装每个资讯对应的栏目、标签、分类
        list.forEach(a -> {
            //封装栏目名称、栏目分类
            ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
            a.setColumnName(contentColumn.getName());
            a.setType(contentColumn.getType());

            //封装推荐标签
            a.setLabelNames(a.getRecommendLabel() != null ? RecommendLabelEnum.getMessage(a.getRecommendLabel()) : null);

            //封装分类
            ContentCategory contentCategory = allCategory.stream().filter(c -> c.getId().equals(a.getThirdlyCategoryId())).findFirst().orElse(new ContentCategory());
            a.setCategoryName(contentCategory.getName());
        });

        return Wrapper.success(new PageData<>(totalCount, list));
    }

    @Override
    @ApiOperation(value = "详情")
    public Wrapper<ContentInformation> get(CommonIdRequest request) {
        ContentInformation contentInformation = contentInformationRepository.findById(request.getId()).orElse(null);
        if (contentInformation == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        return Wrapper.success(contentInformation);
    }

    @Override
    @Transactional
    @ApiOperation(value = "新增")
    public Wrapper<Void> add(ContentInformationRequest request, UserLoginCacheDTO user) {
        //校验推荐标签和排序
        if (request.getRecommendLabel() != null) {
            if (request.getSort() == null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_SORT_CANNOT_BE_EMPTY);
            }
            if (!request.getRecommendLabel().equals(RecommendLabelEnum.THIS_RECOMMENDED.getCode()) && contentInformationRepository.existsBySortAndRecommendLabel(request.getSort(), request.getRecommendLabel())) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_THE_SAME_TAG_SORT_CANNOT_BE_REPEATED);
            }
        } else {
            if (request.getSort() != null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAG_CANNOT_BE_EMPTY);
            }
        }

        //校验所选栏目是否被临时删除或下架
        ContentColumn contentColumn = contentColumnRepository.findById(request.getColumnId()).orElse(null);
        if (contentColumn == null) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_COLUMN_DOES_NOT_EXIST);
        }
        if (contentColumn.getStatus().equals(EnableDisableStatus.DISABLE.getCode())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_COLUMN_STATUS_HAS_EXPIRED);
        }

        //校验所选的标签集合内是否有标签被临时删除或下架
        if (CollectionUtil.isNotEmpty(request.getLabelIds())) {
            List<ContentLabel> contentLabels = contentLabelRepository.findAllByIds(request.getLabelIds());
            if (contentLabels == null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_LABEL_DOES_NOT_EXIST);
            }
            if (contentLabels.size() != request.getLabelIds().size()) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_MISMATCH);
            }
            ContentLabel label = contentLabels.stream().filter(a -> a.getStatus().equals(EnableDisableStatus.DISABLE.getCode())).findFirst().orElse(null);
            if (label != null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_LABEL_STATUS_HAS_EXPIRED);
            }
        }

        //校验推荐标签和栏目分类是否对应
        if (request.getRecommendLabel() != null && request.getRecommendLabel().equals(RecommendLabelEnum.MARKET_RECOMMENDED.getCode()) && !request.getType().equals(ColumnTypeEnum.MARKET.getCode())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAGS_ARE_QUOTES_RECOMMENDATIONS);
        }
        if (request.getRecommendLabel() != null && request.getRecommendLabel().equals(RecommendLabelEnum.THIS_RECOMMENDED.getCode())) {
            if (!request.getType().equals(ColumnTypeEnum.INFORMATION.getCode())) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAGS_ARE_RECOMMENDED_FOR_THIS_COLUMN);
            }
            //每个栏目只能设置一个本栏推荐的资讯
            ContentInformation contentInformation = contentInformationRepository.findByColumnIdAndRecommendLabel(request.getColumnId(), request.getRecommendLabel());
            if (contentInformation != null) {
                contentInformation.setTitle(request.getTitle());
                contentInformation.setSort(request.getSort());
                contentInformation.setReadCount(request.getReadCount());
                contentInformation.setFirstCategoryId(request.getFirstCategoryId());
                contentInformation.setSecondCategoryId(request.getSecondCategoryId());
                contentInformation.setThirdlyCategoryId(request.getThirdlyCategoryId());
                contentInformation.setFirstCategoryName(request.getFirstCategoryName());
                contentInformation.setSecondCategoryName(request.getSecondCategoryName());
                contentInformation.setThirdlyCategoryName(request.getThirdlyCategoryName());
                contentInformation.setLabelIds(request.getLabelIds());
                contentInformation.setImageUrl(request.getImageUrl());
                contentInformation.setDigest(request.getDigest());
                contentInformation.setContent(request.getContent());
                contentInformationRepository.saveAndFlush(contentInformation);
                return Wrapper.success();
            }
        }

        //新增
        ContentInformation contentInformation = new ContentInformation();
        BeanUtils.copyProperties(request, contentInformation);
        contentInformationRepository.saveAndFlush(contentInformation);
        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "修改")
    public Wrapper<Void> update(ContentInformationRequest request, UserLoginCacheDTO user) {
        //校验推荐标签和排序
        if (request.getRecommendLabel() != null) {
            if (request.getSort() == null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_SORT_CANNOT_BE_EMPTY);
            }
            if (!request.getRecommendLabel().equals(RecommendLabelEnum.THIS_RECOMMENDED.getCode())) {
                ContentInformation existsContentInformation = contentInformationRepository.findBySortAndRecommendLabel(request.getSort(), request.getRecommendLabel());
                if (existsContentInformation != null && existsContentInformation.getId() - request.getId() != 0) {
                    return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_THE_SAME_TAG_SORT_CANNOT_BE_REPEATED);
                }
            }
        } else {
            if (request.getSort() != null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAG_CANNOT_BE_EMPTY);
            }
        }

        //校验所选栏目是否被临时删除或下架
        ContentColumn contentColumn = contentColumnRepository.findById(request.getColumnId()).orElse(null);
        if (contentColumn == null) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_COLUMN_DOES_NOT_EXIST);
        }
        if (contentColumn.getStatus().equals(EnableDisableStatus.DISABLE.getCode())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_COLUMN_STATUS_HAS_EXPIRED);
        }

        //校验所选的标签集合内是否有标签被临时删除或下架
        if (CollectionUtil.isNotEmpty(request.getLabelIds())) {
            List<ContentLabel> contentLabels = contentLabelRepository.findAllByIds(request.getLabelIds());
            if (contentLabels == null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_LABEL_DOES_NOT_EXIST);
            }
            if (contentLabels.size() != request.getLabelIds().size()) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_MISMATCH);
            }
            ContentLabel label = contentLabels.stream().filter(a -> a.getStatus().equals(EnableDisableStatus.DISABLE.getCode())).findFirst().orElse(null);
            if (label != null) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_LABEL_STATUS_HAS_EXPIRED);
            }
        }

        //校验推荐标签和栏目分类是否对应
        if (request.getRecommendLabel() != null && request.getRecommendLabel().equals(RecommendLabelEnum.MARKET_RECOMMENDED.getCode()) && !request.getType().equals(ColumnTypeEnum.MARKET.getCode())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAGS_ARE_QUOTES_RECOMMENDATIONS);
        }
        if (request.getRecommendLabel() != null && request.getRecommendLabel().equals(RecommendLabelEnum.THIS_RECOMMENDED.getCode())) {
            if (!request.getType().equals(ColumnTypeEnum.INFORMATION.getCode())) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_TAGS_ARE_RECOMMENDED_FOR_THIS_COLUMN);
            }
            //每个栏目只能设置一个本栏推荐的资讯，所以将旧的本栏推荐资讯删除，避免造成同个栏目有两条本栏推荐资讯
            ContentInformation contentInformation = contentInformationRepository.findByColumnIdAndRecommendLabel(request.getColumnId(), request.getRecommendLabel());
            if (contentInformation != null && contentInformation.getId() - request.getId() != 0) {
                contentInformationRepository.deleteById(contentInformation.getId());
                contentInformationCollectRepository.deleteByInformationId(contentInformation.getId());
            }
        }

        //修改
        ContentInformation contentInformation = contentInformationRepository.findById(request.getId()).orElse(null);
        if (contentInformation == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        if (contentInformation.getStatus().equals(ShelfEnum.ON_SHELF.getCode())) {
            throw new BusinessException(ResponseCode.MAN_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }
        BeanUtils.copyProperties(request, contentInformation);
        contentInformationRepository.saveAndFlush(contentInformation);
        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "上架/下架")
    public Wrapper<Void> updateStatus(CommonStatusRequest request, UserLoginCacheDTO user) {
        ContentInformation contentInformation = contentInformationRepository.findById(request.getId()).orElse(null);
        if (contentInformation == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        contentInformation.setStatus(request.getShelfStatus());
        contentInformationRepository.saveAndFlush(contentInformation);
        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "删除")
    public Wrapper<Void> delete(CommonIdRequest request, UserLoginCacheDTO user) {
        ContentInformation contentInformation = contentInformationRepository.findById(request.getId()).orElse(null);
        if (contentInformation == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        if (contentInformation.getStatus().equals(ShelfEnum.ON_SHELF.getCode())) {
            throw new BusinessException(ResponseCode.MAN_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }
        contentInformationRepository.delete(contentInformation);
        contentInformationCollectRepository.deleteByInformationId(request.getId());
        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "批量删除/上架/下架")
    public Wrapper<Void> batch(ContentInformationBatchRequest request, UserLoginCacheDTO user) {
        //根据资讯ID获取资讯集合
        List<ContentInformation> list = contentInformationRepository.findAllById(request.getIds());

        //批量删除
        if (request.getType() == 1) {
            if (list.stream().anyMatch(a -> a.getStatus().equals(ShelfEnum.ON_SHELF.getCode()))) {
                throw new BusinessException(ResponseCode.MAN_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
            contentInformationRepository.deleteAll(list);
            contentInformationCollectRepository.deleteByInformationIdIn(list.stream().map(ContentInformation::getId).collect(Collectors.toList()));
        }
        //批量上架
        if (request.getType() == 2) {
            if (list.stream().anyMatch(a -> a.getStatus().equals(ShelfEnum.ON_SHELF.getCode()))) {
                throw new BusinessException(ResponseCode.MAN_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
            list = list.stream().peek(a -> a.setStatus(ShelfEnum.ON_SHELF.getCode())).collect(Collectors.toList());
            contentInformationRepository.saveAll(list);
        }
        //批量下架
        if (request.getType() == 3) {
            if (list.stream().anyMatch(a -> !a.getStatus().equals(ShelfEnum.ON_SHELF.getCode()))) {
                throw new BusinessException(ResponseCode.MAN_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
            list = list.stream().peek(a -> a.setStatus(ShelfEnum.OFF_SHELF.getCode())).collect(Collectors.toList());
            contentInformationRepository.saveAll(list);
        }

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "根据推荐标签获取")
    public Wrapper<List<ContentInformationResponse>> findAllByRecommendLabel(RecommendLabelRequest request) {
        List<ContentInformation> list = contentInformationRepository.findAllByRecommendLabelAndStatus(request.getRecommendLabel(), ShelfEnum.ON_SHELF.getCode(), Sort.by("sort"));
        List<ContentColumn> columnList = contentColumnRepository.findAll();
        return Wrapper.success(
                list.stream().map(a -> {
                    ContentInformationResponse response = new ContentInformationResponse();
                    BeanUtils.copyProperties(a, response);
                    ContentColumn contentColumn = columnList.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
                    response.setColumnName(contentColumn.getName());
                    return response;
                }).collect(Collectors.toList())
        );
    }

    @Override
    @ApiOperation(value = "最新发布")
    public Wrapper<List<ContentInformationResponse>> latest() {
        Pageable pageable = PageRequest.of(0, 8, Sort.by("createTime").descending());
        Page<ContentInformation> page = contentInformationRepository.findAllByStatus(ShelfEnum.ON_SHELF.getCode(), pageable);

        List<ContentInformation> list = page.getContent();
        List<ContentColumn> columnList = contentColumnRepository.findAll();
        return Wrapper.success(
                list.stream().map(a -> {
                    ContentInformationResponse response = new ContentInformationResponse();
                    BeanUtils.copyProperties(a, response);
                    ContentColumn contentColumn = columnList.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
                    response.setColumnName(contentColumn.getName());
                    return response;
                }).collect(Collectors.toList())
        );
    }

    @Override
    @ApiOperation(value = "最多阅读")
    public Wrapper<List<ContentInformationResponse>> maximumRead() {
        Pageable pageable = PageRequest.of(0, 8, Sort.by("readCount").descending());
        Page<ContentInformation> page = contentInformationRepository.findAllByStatus(ShelfEnum.ON_SHELF.getCode(), pageable);

        List<ContentInformation> list = page.getContent();
        List<ContentColumn> columnList = contentColumnRepository.findAll();
        return Wrapper.success(
                list.stream().map(a -> {
                    ContentInformationResponse response = new ContentInformationResponse();
                    BeanUtils.copyProperties(a, response);
                    ContentColumn contentColumn = columnList.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
                    response.setColumnName(contentColumn.getName());
                    return response;
                }).collect(Collectors.toList())
        );
    }

    @Override
    @ApiOperation(value = "最多收藏")
    public Wrapper<List<ContentInformationResponse>> maximumCollect() {
        Pageable pageable = PageRequest.of(0, 8, Sort.by("collectCount").descending());
        Page<ContentInformation> page = contentInformationRepository.findAllByStatus(ShelfEnum.ON_SHELF.getCode(), pageable);

        List<ContentInformation> list = page.getContent();
        List<ContentColumn> columnList = contentColumnRepository.findAll();
        return Wrapper.success(
                list.stream().map(a -> {
                    ContentInformationResponse response = new ContentInformationResponse();
                    BeanUtils.copyProperties(a, response);
                    ContentColumn contentColumn = columnList.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
                    response.setColumnName(contentColumn.getName());
                    return response;
                }).collect(Collectors.toList())
        );
    }

    @Override
    @ApiOperation(value = "根据分类获取")
    public Wrapper<List<InformationColumnResponse>> findAllByCategory(CommonIdRequest request) {
        //获取所有栏目
        List<ContentColumn> columnList = contentColumnRepository.findAllByStatus(CommonBooleanEnum.YES.getCode(), Sort.by("sort"));
        if (CollectionUtil.isEmpty(columnList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //根据栏目ID集合、分类ID获取资讯
        List<ContentInformation> list = contentInformationRepository.findAllByColumnIdInAndStatusAndThirdlyCategoryId(
                columnList.stream().map(ContentColumn::getId).collect(Collectors.toList()),
                ShelfEnum.ON_SHELF.getCode(),
                request.getId()
        );

        //筛选出有资讯数据的栏目
        columnList = columnList.stream().filter(a ->
                list.stream().anyMatch(b -> b.getColumnId().equals(a.getId()))
        ).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(columnList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //根据栏目ID分组获取每一组栏目下的资讯
        Map<Long, List<ContentInformation>> map = list.stream().collect(Collectors.groupingBy(ContentInformation::getColumnId));

        //封装每一组栏目下的资讯（资讯按发布时间倒序，每一组栏目展示8条资讯）
        List<InformationColumnResponse> responseList = columnList.stream().map(a -> {
            InformationColumnResponse response = new InformationColumnResponse();
            response.setColumnId(a.getId());
            response.setColumnName(a.getName());

            List<ContentInformation> informationList = map.get(a.getId());
            if (CollectionUtil.isNotEmpty(informationList)) {

                informationList = informationList.stream().sorted(Comparator.comparingLong(
                        ContentInformation::getCreateTime
                ).reversed()).collect(Collectors.toList());

                response.setList(informationList.stream().limit(8).collect(Collectors.toList()));
            }

            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(responseList);
    }

    @Override
    @ApiOperation(value = "根据栏目获取")
    public Wrapper<PageData<ContentInformationResponse>> pageByColumnLabel(CommonIdPageRequest request) {
        Pageable pageable = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("createTime").descending());
        Page<ContentInformation> page = contentInformationRepository.findAllByStatusAndColumnId(ShelfEnum.ON_SHELF.getCode(), request.getId(), pageable);

        List<ContentColumn> columnList = contentColumnRepository.findAll();
        List<ContentInformationResponse> list = page.getContent().stream().map(a -> {
            ContentInformationResponse response = new ContentInformationResponse();
            BeanUtils.copyProperties(a, response);
            ContentColumn contentColumn = columnList.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
            response.setColumnName(contentColumn.getName());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(page.getTotalElements(), list));
    }

    @Override
    @ApiOperation(value = "资讯栏目")
    public Wrapper<List<InformationColumnResponse>> informationColumn() {
        //获取所有栏目分类为'资讯'的栏目
        List<ContentColumn> columnList = contentColumnRepository.findAllByStatusAndType(CommonBooleanEnum.YES.getCode(), ColumnTypeEnum.INFORMATION.getCode(), Sort.by("sort"));
        if (CollectionUtil.isEmpty(columnList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //根据栏目ID集合获取资讯
        List<ContentInformation> list = contentInformationRepository.findAllByColumnIdInAndStatus(
                columnList.stream().map(ContentColumn::getId).collect(Collectors.toList()),
                ShelfEnum.ON_SHELF.getCode()
        );

        //筛选出有资讯数据的栏目
        columnList = columnList.stream().filter(a ->
                list.stream().anyMatch(b -> b.getColumnId().equals(a.getId()))
        ).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(columnList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //根据栏目ID分组获取每一组栏目下的资讯
        Map<Long, List<ContentInformation>> map = list.stream().collect(Collectors.groupingBy(ContentInformation::getColumnId));

        //如果栏目下有'本栏推荐'的资讯需要移动下标到第一
        List<InformationColumnResponse> responseList = columnList.stream().map(a -> {
            InformationColumnResponse response = new InformationColumnResponse();
            response.setColumnId(a.getId());
            response.setColumnName(a.getName());

            List<ContentInformation> informationList = map.get(a.getId());
            if (CollectionUtil.isNotEmpty(informationList)) {
                ContentInformation contentInformation = null;
                for (int i = 0; i < informationList.size(); i++) {
                    ContentInformation information = informationList.get(i);
                    if (information.getRecommendLabel() != null && information.getRecommendLabel().equals(RecommendLabelEnum.THIS_RECOMMENDED.getCode())) {
                        contentInformation = informationList.remove(i);
                        break;
                    }
                }

                informationList = informationList.stream().sorted(Comparator.comparingLong(
                        ContentInformation::getCreateTime
                ).reversed()).collect(Collectors.toList());

                if (contentInformation != null) {
                    informationList.add(0, contentInformation);
                }

                response.setList(informationList.stream().limit(8).collect(Collectors.toList()));
            }

            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(responseList);
    }

    @Override
    @ApiOperation(value = "搜索")
    public Wrapper<PageData<ContentInformationResponse>> search(ContentInformationSearchRequest request) {
        QContentInformation qContentInformation = QContentInformation.contentInformation;
        JPAQuery<ContentInformationResponse> jpaQuery = jpaQueryFactory
                .select(Projections.constructor(ContentInformationResponse.class,
                        qContentInformation.id,
                        qContentInformation.columnId,
                        qContentInformation.title,
                        qContentInformation.recommendLabel,
                        qContentInformation.sort,
                        qContentInformation.labelIds,
                        qContentInformation.imageUrl,
                        qContentInformation.digest,
                        qContentInformation.content,
                        qContentInformation.status,
                        qContentInformation.createTime,
                        qContentInformation.collectCount))
                .from(qContentInformation);
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(qContentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));
        if (StringUtils.isNotBlank(request.getKeyword())) {
            //标题
            builder.and(qContentInformation.title.contains(request.getKeyword()));

            //栏目
            List<ContentColumn> columnList = contentColumnRepository.findAllByNameContainingAndStatus(request.getKeyword(), CommonBooleanEnum.YES.getCode());
            if (CollectionUtil.isNotEmpty(columnList)) {
                List<Long> columnIdList = columnList.stream().map(ContentColumn::getId).collect(Collectors.toList());
                builder.or(qContentInformation.columnId.in(columnIdList));
            }

            //一级分类、二级分类、三级分类
            List<ContentCategory> categoryList = contentCategoryRepository.findAllByNameContaining(request.getKeyword());
            if (CollectionUtil.isNotEmpty(categoryList)) {
                List<Long> firstCategoryIdList = categoryList.stream().filter(a -> a.getLevel().equals(1)).map(ContentCategory::getId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(firstCategoryIdList)) {
                    builder.or(qContentInformation.firstCategoryId.in(firstCategoryIdList));
                }
                List<Long> secondCategoryIdList = categoryList.stream().filter(a -> a.getLevel().equals(2)).map(ContentCategory::getId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(secondCategoryIdList)) {
                    builder.or(qContentInformation.secondCategoryId.in(secondCategoryIdList));
                }
                List<Long> thirdlyCategoryIdList = categoryList.stream().filter(a -> a.getLevel().equals(3)).map(ContentCategory::getId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(thirdlyCategoryIdList)) {
                    builder.or(qContentInformation.thirdlyCategoryId.in(thirdlyCategoryIdList));

                }
            }

            //摘要
            builder.or(qContentInformation.digest.contains(request.getKeyword()));

            //文章内容
            builder.or(qContentInformation.content.contains(request.getKeyword()));
        }


        long totalCount = jpaQuery.where(builder).fetchCount();
        List<ContentInformationResponse> list = jpaQuery.orderBy(qContentInformation.createTime.desc()).limit(request.getPageSize()).offset((long) (request.getCurrent() - 1) * request.getPageSize()).fetch();

        //获取所有栏目
        List<ContentColumn> allColumn = contentColumnRepository.findAll();

        //封装栏目名称
        list.forEach(a -> {
            ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
            a.setColumnName(contentColumn.getName());
        });

        return Wrapper.success(new PageData<>(totalCount, list));
    }

    @Override
    @ApiOperation(value = "根据ID获取")
    public Wrapper<ContentInformationResponse> findById(CommonIdRequest request, UserLoginCacheDTO user) {
        //根据id获取资讯
        ContentInformation information = contentInformationRepository.findById(request.getId()).orElse(null);
        if (information == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        if (information.getStatus().equals(ShelfEnum.OFF_SHELF.getCode())) {
            throw new BusinessException(ResponseCode.MAN_DISABLE);
        }

        //拷贝
        ContentInformationResponse response = new ContentInformationResponse();
        BeanUtils.copyProperties(information, response);

        //栏目名称
        ContentColumn contentColumn = contentColumnRepository.findById(response.getColumnId()).orElse(new ContentColumn());
        response.setColumnName(contentColumn.getName());

        //上一篇/下一篇
        List<ContentInformation> list = contentInformationRepository.findAllByColumnIdAndStatus(information.getColumnId(), ShelfEnum.ON_SHELF.getCode(), Sort.by("createTime").descending());
        for (int i = 0; i < list.size(); i++) {
            ContentInformation contentInformation = list.get(i);
            if (contentInformation.getId().equals(response.getId())) {
                if (i != 0) {
                    ContentInformation lastContentLabel = list.get(i - 1);
                    response.setLastContentLabel(lastContentLabel);
                }
                if (list.size() - 1 != i) {
                    ContentInformation nextContentLabel = list.get(i + 1);
                    response.setNextContentLabel(nextContentLabel);
                }
                break;
            }
        }

        //收藏状态
        if (user != null) {
            Boolean collectStatus = contentInformationCollectRepository.existsByInformationIdAndMemberIdAndUserId(information.getId(), user.getMemberId(), user.getUserId());
            response.setCollectStatus(collectStatus);
        }

        //查看详情增加浏览量
        information.setReadCount(information.getReadCount() + 1);
        contentInformationRepository.saveAndFlush(information);

        return Wrapper.success(response);
    }

    @Override
    @ApiOperation(value = "根据ID集合获取")
    public Wrapper<List<ContentInformationListResponse>> findByIdIn(CommonIdListRequest request) {
        //根据资讯ID集合获取资讯
        List<ContentInformation> list = contentInformationRepository.findAllById(request.getIdList());
        if (CollectionUtil.isEmpty(list)) {
            return Wrapper.success(new ArrayList<>());
        }

        //获取所有栏目
        List<ContentColumn> allColumn = contentColumnRepository.findAll();

        //封装
        return Wrapper.success(
                list.stream().sorted(Comparator.comparingInt(a ->
                        request.getIdList().indexOf(a.getId())
                )).map(a -> {
                    ContentInformationListResponse response = new ContentInformationListResponse();
                    BeanUtils.copyProperties(a, response);
                    ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(new ContentColumn());
                    response.setColumnName(contentColumn.getName());
                    return response;
                }).collect(Collectors.toList())
        );
    }

    public static void main(String[] args) {
        Random random = new Random(1);
        int i = random.nextInt(100);
        System.out.println(i);
    }

    @Override
    @ApiOperation(value = "同类资讯")
    public Wrapper<List<ContentInformationResponse>> related(CommonIdRequest request) {
        //根据id获取资讯
        ContentInformation information = contentInformationRepository.findById(request.getId()).orElse(null);
        if (information == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        //获取数据库最大数
        QContentInformation qContentInformation = QContentInformation.contentInformation;
        JPAQuery<ContentInformationResponse> jpaQuery = jpaQueryFactory
                .select(Projections.constructor(ContentInformationResponse.class,
                        qContentInformation.id,
                        qContentInformation.columnId,
                        qContentInformation.title,
                        qContentInformation.recommendLabel,
                        qContentInformation.sort,
                        qContentInformation.labelIds,
                        qContentInformation.imageUrl,
                        qContentInformation.digest,
                        qContentInformation.content,
                        qContentInformation.status,
                        qContentInformation.createTime,
                        qContentInformation.collectCount))
                .from(qContentInformation);
        jpaQuery.where(qContentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));
        if (information.getThirdlyCategoryId() != null) {
            jpaQuery.where(qContentInformation.thirdlyCategoryId.eq(information.getThirdlyCategoryId()));
        }
        int totalCount = (int) jpaQuery.fetchCount();
        if (totalCount > 8) {
            totalCount = new Random().nextInt(totalCount - 8);//获取随机8条数据
        }
        //根据相同栏目与分类获取相关资讯
        List<ContentInformationResponse> randomList = jpaQuery.limit(8).offset(totalCount).fetch();

        return Wrapper.success(randomList);
    }

    @Override
    @Transactional
    @ApiOperation(value = "收藏/取消收藏")
    public Wrapper<Void> collect(CollectRequest request, UserLoginCacheDTO userDTO) {
        if (request.getStatus()) {
            if (contentInformationCollectRepository.existsByInformationIdAndMemberIdAndUserId(request.getInformationId(), userDTO.getMemberId(), userDTO.getUserId())) {
                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_CAN_T_BE_REPEATED);
            }
            ContentInformationCollect collect = new ContentInformationCollect();
            collect.setInformationId(request.getInformationId());
            collect.setMemberId(userDTO.getMemberId());
            collect.setUserId(userDTO.getUserId());
            contentInformationCollectRepository.saveAndFlush(collect);
        } else {
            contentInformationCollectRepository.deleteByInformationIdAndMemberIdAndUserId(request.getInformationId(), userDTO.getMemberId(), userDTO.getUserId());
        }
        ContentInformation contentInformation = contentInformationRepository.findById(request.getInformationId()).orElse(null);
        if (contentInformation != null) {
            //更新资讯收藏数
            contentInformation.setCollectCount(request.getStatus() ? 1 : -1);
            contentInformationRepository.saveAndFlush(contentInformation);
        }
        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "收藏列表")
    public Wrapper<PageData<ContentInformationResponse>> collectList(PageVO request, UserLoginCacheDTO userDTO) {
        //分页查询当前登录用户收藏资讯信息
        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("createTime").descending());
        Page<ContentInformationCollect> result = contentInformationCollectRepository.findAllByMemberIdAndUserId(userDTO.getMemberId(), userDTO.getUserId(), page);
        List<ContentInformationCollect> contentInformationResponseList = result.getContent();

        if (CollectionUtil.isNotEmpty(contentInformationResponseList)) {
            List<Long> informationIdList = contentInformationResponseList.stream().map(ContentInformationCollect::getInformationId).collect(Collectors.toList());
            List<ContentInformation> allByIds = contentInformationRepository.findAllById(informationIdList);
            if (CollectionUtil.isNotEmpty(allByIds)) {
                List<ContentColumn> allColumn = contentColumnRepository.findAll();
                List<ContentLabel> allLabel = contentLabelRepository.findAll();

                List<ContentInformationResponse> responses = allByIds.stream().map(a -> {
                    ContentInformationResponse response = new ContentInformationResponse();
                    BeanUtils.copyProperties(a, response);

                    ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(null);
                    response.setColumnName(contentColumn == null ? "" : contentColumn.getName());

                    if (CollectionUtil.isNotEmpty(a.getLabelIds())) {
                        List<Map<String, Object>> contentLabelList = allLabel.stream()
                                .filter(b -> a.getLabelIds().stream().anyMatch(c -> c.equals(b.getId())))
                                .map(d -> {
                                    Map<String, Object> contentLabel = new HashMap<>();
                                    contentLabel.put("id", d.getId());
                                    contentLabel.put("name", d.getName());
                                    return contentLabel;
                                }).collect(Collectors.toList());
                        response.setContentLabelList(contentLabelList);
                    }

                    Long collectTime = contentInformationResponseList.stream().filter(b -> b.getInformationId().equals(a.getId())).mapToLong(ContentInformationCollect::getCreateTime).findFirst().orElse(0L);
                    response.setCollectTime(collectTime);
                    return response;
                }).sorted(Comparator.comparing(ContentInformationResponse::getCollectTime).reversed()).collect(Collectors.toList());

                return Wrapper.success(new PageData<>(result.getTotalElements(), responses));
            }
        }

        return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
    }

    @Override
    @ApiOperation(value = "列表（装修）")
    public Wrapper<PageData<ContentInformationListAdornResponse>> listAdorn(ContentInformationListAdornRequest request) {
        //查询表实体 - 资讯
        QContentInformation contentInformation = QContentInformation.contentInformation;

        //查询条件构造 - 必要条件
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(contentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));

        //搜索条件
        if (StringUtils.isNotBlank(request.getTitle())) {
            predicates.and(contentInformation.title.like("%" + request.getTitle() + "%"));
        }
        if (request.getIdInList() != null) {
            predicates.and(contentInformation.id.in(request.getIdInList()));
        }
        if (request.getIdNotInList() != null) {
            predicates.and(contentInformation.id.notIn(request.getIdNotInList()));
        }

        //查询
        JPAQuery<ContentInformationListAdornResponse> query = jpaQueryFactory.select(
                Projections.bean(
                        ContentInformationListAdornResponse.class,
                        contentInformation.id,
                        contentInformation.columnId,
                        contentInformation.title,
                        contentInformation.imageUrl,
                        contentInformation.createTime
                )
        ).from(contentInformation).where(predicates);

        //总记录数
        long totalCount = query.fetchCount();

        //列表数据
        List<ContentInformationListAdornResponse> list = query.orderBy(contentInformation.createTime.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize()).fetch();

        //封装栏目名称
        List<ContentColumn> allColumn = contentColumnRepository.findAll();
        list = list.stream().peek(a -> {
            ContentColumn contentColumn = allColumn.stream().filter(b ->
                    b.getId().equals(a.getColumnId())
            ).findFirst().orElse(new ContentColumn());
            a.setColumnName(contentColumn.getName());
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(totalCount, list));
    }

    /**
     * 根据不包含的资讯ID分页获取资讯列表
     */
    @Override
    public Wrapper<PageData<ContentInformationResponse>> pageByIdNotIn(CommonIdListPageRequest request) {
        QContentInformation qContentInformation = QContentInformation.contentInformation;
        JPAQuery<ContentInformationResponse> jpaQuery = jpaQueryFactory
                .select(Projections.constructor(ContentInformationResponse.class,
                        qContentInformation.id,
                        qContentInformation.columnId,
                        qContentInformation.title,
                        qContentInformation.recommendLabel,
                        qContentInformation.sort,
                        qContentInformation.labelIds,
                        qContentInformation.imageUrl,
                        qContentInformation.digest,
                        qContentInformation.content,
                        qContentInformation.status,
                        qContentInformation.createTime,
                        qContentInformation.collectCount))
                .from(qContentInformation);
        jpaQuery.where(qContentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));

        if (request.getType() != null) {
            List<ContentColumn> columnList = contentColumnRepository.findAllByStatusAndType(CommonBooleanEnum.YES.getCode(), request.getType());
            if (CollectionUtil.isNotEmpty(columnList)) {
                List<Long> columnIdList = columnList.stream().map(ContentColumn::getId).collect(Collectors.toList());
                jpaQuery.where(qContentInformation.columnId.in(columnIdList));
            }
        }
        if (request.getColumnId() != null) {
            jpaQuery.where(qContentInformation.columnId.eq(request.getColumnId()));
        }
        if (CollectionUtil.isNotEmpty(request.getIdList())) {
            jpaQuery.where(qContentInformation.id.in(request.getIdList()));
        }
        long totalCount = jpaQuery.fetchCount();
        List<ContentInformationResponse> list = jpaQuery.orderBy(qContentInformation.createTime.desc()).limit(request.getPageSize()).offset(request.getCurrentOffset()).fetch();
        //获取所有栏目
        List<ContentColumn> allColumn = contentColumnRepository.findAll();

        //封装每个资讯对应的栏目
        list.forEach(a -> {
            ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(null);
            a.setColumnName(contentColumn == null ? "" : contentColumn.getName());
        });

        return Wrapper.success(new PageData<>(totalCount, list));
    }

    /**
     * 根据包含的资讯ID分页获取资讯列表
     */
    @Override
    public Wrapper<PageData<ContentInformationResponse>> pageByIdIn(CommonIdListPageRequest request) {

        QContentInformation qContentInformation = QContentInformation.contentInformation;
        JPAQuery<ContentInformationResponse> jpaQuery = jpaQueryFactory
                .select(Projections.constructor(ContentInformationResponse.class,
                        qContentInformation.id,
                        qContentInformation.columnId,
                        qContentInformation.title,
                        qContentInformation.recommendLabel,
                        qContentInformation.sort,
                        qContentInformation.labelIds,
                        qContentInformation.imageUrl,
                        qContentInformation.digest,
                        qContentInformation.content,
                        qContentInformation.status,
                        qContentInformation.createTime,
                        qContentInformation.collectCount))
                .from(qContentInformation);
        jpaQuery.where(qContentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));

        if (CollectionUtil.isNotEmpty(request.getIdList())) {
            jpaQuery.where(qContentInformation.id.in(request.getIdList()));
        } else {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
        long totalCount = jpaQuery.fetchCount();
        List<ContentInformationResponse> list = jpaQuery.orderBy(qContentInformation.createTime.desc()).limit(request.getPageSize()).offset(request.getCurrentOffset()).fetch();

        //获取所有栏目
        List<ContentColumn> allColumn = contentColumnRepository.findAll();

        //封装每个资讯对应的栏目
        list.forEach(a -> {
            ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(null);
            a.setColumnName(contentColumn == null ? "" : contentColumn.getName());
        });

        return Wrapper.success(new PageData<>(totalCount, list));
    }

}